#include "muduo/proto/codec.h"
#include "muduo/proto/dispatcher.h"
#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include "request.pb.h"
#include <iostream>
#include <unordered_map>

/**
 * 基于Muduo网络库的Protobuf服务器类
 * 支持处理两种类型的请求：翻译请求和加法请求
 */
class Server {
public:
    typedef std::shared_ptr<google::protobuf::Message> MessagePtr;
    typedef std::shared_ptr<zdf::TranslateRequest> TranslateRequestPtr;
    typedef std::shared_ptr<zdf::AddRequest> AddRequestPtr;

    /**
     * 构造函数
     * @param port 服务器监听端口
     */
    Server(int port)
        : _server(&_baseloop, muduo::net::InetAddress("0.0.0.0", port), 
                 "Server", muduo::net::TcpServer::kReusePort),
          _dispatcher(std::bind(&Server::onUnknownMessage, this, std::placeholders::_1, 
                              std::placeholders::_2, std::placeholders::_3)),
          _codec(std::bind(&ProtobufDispatcher::onProtobufMessage, &_dispatcher, 
                          std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) {
        
        // 注册业务请求处理函数
        // 当收到TranslateRequest类型的消息时，调用onTranslate方法处理
        _dispatcher.registerMessageCallback<zdf::TranslateRequest>(std::bind(&Server::onTranslate, this, 
                                                                          std::placeholders::_1, 
                                                                          std::placeholders::_2, 
                                                                          std::placeholders::_3));
                
        // 当收到AddRequest类型的消息时，调用onAdd方法处理
        _dispatcher.registerMessageCallback<zdf::AddRequest>(std::bind(&Server::onAdd, this, 
                                                                       std::placeholders::_1, 
                                                                       std::placeholders::_2, 
                                                                       std::placeholders::_3));

        // 设置消息回调函数，当有新消息到达时，由_codec进行解析
        _server.setMessageCallback(std::bind(&ProtobufCodec::onMessage, &_codec,
                                           std::placeholders::_1, 
                                           std::placeholders::_2, 
                                           std::placeholders::_3));
        
        // 设置连接回调函数，处理连接建立和断开事件
        _server.setConnectionCallback(std::bind(&Server::onConnection, this, std::placeholders::_1));
    }

    /**
     * 启动服务器
     */
    void start() {
        _server.start();
        _baseloop.loop();
    }

private:
    /**
     * 简单的翻译功能实现
     * @param str 待翻译的字符串
     * @return 翻译结果
     */
    std::string translate(const std::string &str) {
        // 简单的字典映射，实际应用中可以替换为更复杂的翻译引擎
        static std::unordered_map<std::string, std::string> dict_map = {
            {"hello", "你好"},
            {"Hello", "你好"},
            {"你好", "Hello"},
            {"吃了吗", "油泼面"}  // 示例中的趣味翻译
        };
        
        auto it = dict_map.find(str);
        if (it == dict_map.end()) {
            return "没听懂！！";
        }
        return it->second;
    }

    /**
     * 处理翻译请求
     * @param conn 客户端连接
     * @param message 翻译请求消息
     * @param time 消息到达时间
     */
    void onTranslate(const muduo::net::TcpConnectionPtr& conn, const TranslateRequestPtr& message, muduo::Timestamp) {
        // 1. 提取message中的有效消息，也就是需要翻译的内容
        std::string req_msg = message->msg();
        
        // 2. 进行翻译，得到结果
        std::string rsp_msg = translate(req_msg);
        
        // 3. 组织protobuf的响应
        zdf::TranslateResponse resp;
        resp.set_msg(rsp_msg);
        
        // 4. 发送响应
        _codec.send(conn, resp);
    }

    /**
     * 处理加法请求
     * @param conn 客户端连接
     * @param message 加法请求消息
     * @param time 消息到达时间
     */
    void onAdd(const muduo::net::TcpConnectionPtr& conn, const AddRequestPtr& message, muduo::Timestamp) {
        int num1 = message->num1();
        int num2 = message->num2();
        int result = num1 + num2;
        
        zdf::AddResponse resp;
        resp.set_result(result);
        
        _codec.send(conn, resp);
    }

    /**
     * 处理未知类型的消息
     * @param conn 客户端连接
     * @param message 未知类型的消息
     * @param time 消息到达时间
     */
    void onUnknownMessage(const muduo::net::TcpConnectionPtr& conn, const MessagePtr& message, muduo::Timestamp) {
        LOG_INFO << "onUnknownMessage: " << message->GetTypeName();
        // 对于未知类型的消息，关闭连接
        conn->shutdown();
    }

    /**
     * 处理连接事件
     * @param conn 客户端连接
     */
    void onConnection(const muduo::net::TcpConnectionPtr &conn) {
        if (conn->connected()) {
            LOG_INFO << "新连接建立成功！";
        } else {
            LOG_INFO << "连接即将关闭！";
        }
    }

private:
    muduo::net::EventLoop _baseloop;               // 主事件循环
    muduo::net::TcpServer _server;                 // 服务器对象
    ProtobufDispatcher _dispatcher;                // 请求分发器，根据消息类型分发到不同的处理函数
    ProtobufCodec _codec;                          // Protobuf协议编解码器，负责消息的序列化和反序列化
};

int main()
{
    Server server(8085);
    server.start();
    return 0;
}    